#ifndef __TERRAIN_UPDATER_H__
#define __TERRAIN_UPDATER_H__

#include <cstdint>
#include <set>
#include <atomic>
#include "Engine/Point2.hpp"
#include "Engine/Point3.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    class SubsystemTerrain;
    class SubsystemWeather;
    class SubsystemPlayers;
    class SubsystemTimeOfDay;
    class TerrainChunk;
    class SubsystemBlockBehaviors;

    class TerrainUpdater
    {
    protected:
        SubsystemTerrain *m_subsystemTerrain;
        SubsystemWeather *m_subsystemWeather;
        SubsystemPlayers *m_subsystemPlayers;
        SubsystemTimeOfDay *m_subsystemTimeOfDay;
        SubsystemBlockBehaviors *m_subsystemBlockBehaviors;

        int32_t m_lastSkylightValue;
        float m_isResetSkylightValue;
        std::set<Point2> m_waitUpdateSingleStepCoordSet;


    protected:
        struct LightSource
        {
            constexpr inline LightSource(int32_t x, int32_t y, int32_t z, int32_t theLight) : point(x, y, z), light(theLight) {}

            Point3 point;
            int32_t light;
        };

        std::atomic<bool> playersRoundCheckFinish;

    protected:
        virtual void generateChunkSunLightAndHeight(TerrainChunk* chunk, int32_t skyLightValue);
        virtual void generateChunkLightSources(TerrainChunk *chunk, std::vector<LightSource> &lightSourceVec);
        virtual void updateChunkSingleStep(TerrainChunk *chunk, int32_t skylightValue);
        virtual void propagateLight(TerrainChunk *chunk, std::vector<LightSource> &lightSourceVec);

        virtual void playersRoundCheck();

    public:
        TerrainUpdater();
        virtual ~TerrainUpdater();

        virtual void loadChunk(TerrainChunk *chunk);
        virtual void update(float dt);

    };
    
}

#endif
